import { BoxLayout, StrictBoxLayout } from '../typings/StyleType';
import AbstractScene from './AbstractScene';
import BoxBuffer from '../buffers/BoxBuffer';

interface GeometryRender {
    buffer: BoxBuffer;
    opacity: number;
}

class BoxScene extends AbstractScene<StrictBoxLayout> {
    static readonly DEFAULT_LAYOUT = {
        visible: true,
        opacity: 1,
    };
    static readonly TEXTURE_PARAMS = { xRepeat: false, yRepeat: false };

    private _geometryRenderList: GeometryRender[] = [];

    constructor(layout: BoxLayout) {
        super('Box', { ...BoxScene.DEFAULT_LAYOUT, ...layout });
    }

    clear() {
        this._geometryRenderList.length = 0;
    }

    getGeometryRenderList() {
        return this._geometryRenderList;
    }

    protected async _update() {
        if (!this._layout.visible || !this._engine) return;
        // init front
        await this._init([
            -1, 1, 1,
            -1, 1, -1,
            1, 1, 1,
            1, 1, -1,
        ], `${this._layout.url}/front.jpg`);
        // init left
        await this._init([
            -1, -1, 1,
            -1, -1, -1,
            -1, 1, 1,
            -1, 1, -1,
        ], `${this._layout.url}/left.jpg`);
        // init right
        await this._init([
            1, 1, 1,
            1, 1, -1,
            1, -1, 1,
            1, -1, -1,
        ], `${this._layout.url}/right.jpg`);
        // init back
        await this._init([
            1, -1, 1,
            1, -1, -1,
            -1, -1, 1,
            -1, -1, -1,
        ], `${this._layout.url}/back.jpg`);
        this._engine.render();
        // init top
        await this._init([
            -1, -1, 1,
            -1, 1, 1,
            1, -1, 1,
            1, 1, 1,
        ], `${this._layout.url}/top.jpg`);
        // init bottom
        await this._init([
            -1, 1, -1,
            -1, -1, -1,
            1, 1, -1,
            1, -1, -1,
        ], `${this._layout.url}/bottom.jpg`);
        this._engine.render();
    }

    private async _init(vertices: number[], url: string) {
        if (!this._engine) return;
        const textureMng = this._engine.getTextureManager();
        let texture = textureMng.getTexture(url, BoxScene.TEXTURE_PARAMS);
        if (!texture) {
            texture = await textureMng.loadTexture(url, BoxScene.TEXTURE_PARAMS);
        }
        const buffer = new BoxBuffer(this._engine.getGl());
        buffer.update({
            vertices,
            texCoords: [0, 1, 0, 0, 1, 1, 1, 0],
            texture: texture.texture,
        });

        this._geometryRenderList.push({
            opacity: this._layout.opacity,
            buffer,
        });
    }

    setLayout(layout: BoxLayout) {
        this._layout = { ...this._layout, ...layout };
        this._update();
        this._engine && this._engine.render();
    }
}

export default BoxScene;
